/**
*
* Orion 20m v1.0
* (c) 2004 Erik Anderson (Sputnik)
* erik_h_anderson@hotmail.com
*
*
* Licence LGPL -- http://www.gnu.org/licenses/lgpl.txt
*
* You may use this source code in your addon provided that if you
* publish your addon either privately or publicly the end user
* recieves a copy of the source code including any modifications
* you may have made. 
*
* 
*
* Requires CVEL library --                             
* please see ProjectGanymede on SourceForge for the latest source *
*/


#ifndef _ORION20M_H_
#define _ORION20M_H_



#define CVEL
#include <cvel.h>

#include <OrbiterSoundSDK.h>
#include <UMmuSDK.h>
#include <cstdio>

#define DEBUG 1
//#define TESTING 1
#if DEBUG >= 1
#define dprint(s, ...) {char _buf[2048];char _fmt[512];\
	SYSTEMTIME st;::GetSystemTime(&st);\
sprintf_s(_fmt,512,"orion -- %.10f -- %02d %02d %02d %.4d -- %s",oapiGetSysTime(),st.wHour,st.wMinute,st.wSecond,st.wMilliseconds,s);\
	sprintf_s(_buf,2048,_fmt,__VA_ARGS__);\
	oapiWriteLog(_buf);\
}
#else
#define dprint(s, ...) {}
#endif

//#define BUFFERhud 1

#define syslog(s, ...) {char _fmt[1024];\
	lcount++;\
sprintf_s(_fmt,"[%d] %.6f - %s",lcount,oapiGetSimMJD(),s);\
	sprintf_s(shiplog[syslogp].message,1024,_fmt,__VA_ARGS__);\
	syslogp=(syslogp+1)%SYSLOGSIZE;\
}


using std::string;
//#define BOMBFUEL 1
	CONST double OrionVersion = 2.00;
	CONST double MainThrust = 76500000;
	CONST double RCSThrust = 150000;// Now scaled to front rcs, thruster in rear quad is * 4
	CONST double GyroThrust = 450000;//
#ifdef BOMBFUEL	// depricated for now
	CONST double EmptyMass =  4620000.0;
	CONST double Ispmain = 600000000000;
	CONST double FuelMass = 1000000.0; // .5mt bomb * 2000
#else
	CONST double EmptyMass =  580000.0;
	CONST double Ispmain = 37500;
	CONST double FuelMass =  4980000.0;//5040000.0; // 1955 2578.005115kg bombs
#endif

//jupiter 209k FPS 100KG payload
// prp 4770000
//prp mod 376k + prp mag 204k + rcs 53k + oper/payload 392k
//380 + 200 + 290
// isp 3150sec, thrust 16x10e6N 16000000
//CONST double EmptyMass = 870000
//CONST double FuelMass =  4773000

	CONST double IspRCS = 5000;////4200;
	CONST double IspGYRO = 9.9e20;//9;
	CONST double SLAM_SPEED = 1.1;				// About 1/Hz, or a little slower
	

	CONST double GyroFuelMass = 100.0; // ecells? todo: power mgmt.
	CONST double RCSFuelMass = 120000.0;//60000.0;
	CONST double DestructRange = 2000.0;
	CONST double FlashSize = 800.0;
	CONST double VisLimit = 0.001;
	CONST VECTOR3 ExplosionPosition = _V(0,0,-75.0);

#define CAMERAOFS _V(0,0,38.0)
#ifdef TESTING
#define HUDMENUCOUNT 5
#else
#define HUDMENUCOUNT 4
#endif

#define RCS_LIN_F_ZPOS	30.0
#define RCS_LIN_B_ZPOS	-7.5
#define RCS_LIN_F_XYOFF	3.8
#define RCS_LIN_B_XYOFF	7.0
#define RCS_LIN_F_RATIO	1
#define RCS_LIN_B_RATIO	4


#ifdef CVEL
#define API COMMON_VESSEL_EX
#else
#define API VESSEL3
#endif

#define NUMDOCKS 9



class ORIONCFG {
	public:
	double EmptyMass;
	double MainThrust,RCSThrust,GyroThrust;
	double Ispmain,IspRCS,IspGYRO;
	double FuelMass,RCSFuelMass,GyroFuelMass;
	double DestructRange;
	int Destructive;
	double FlashSize,VisLimit;
	DWORD hudfontcolor,hudshadowcolor,hudselcolor,hudmesgcolor,hudfillcolor;
	//double 
	int hudmode;
	int selmmu;
	int seldock;
	int docklight;
	int nukearmed;
	int nukesafety1;
	int nukesafety2;
	int nukesafety3;
	int nukewarned;
	int syslogp;
	int booting;
	double nukeyield;
	int nukeready;
	int rcs_cog_comp;
	int cam;
	bool caminternal;
	bool hudshadow;
	double camyawmode;
	double campitchmode;
	double camanimlink;
	int verbose;
};


class ORIONHUDDATA {
	public:
	double vehmasst,vehmassf,rembombs,thlevel,thmax,thisp;
	double maxfuelmain, currfuelmain, fuelratiomain,tDVmain,remDVmain,remDVmainstack,penaltyDVmain;
	double maxfuelrcs, currfuelrcs, fuelratiorcs,tDVrcs,remDVrcs,remDVrcsstack,penaltyDVrcs;
	double ssmass;
	VECTOR3 vehthrustv,vehtorquev,vehweightv,vehsscg;
	VECTOR3 thdirmain,threfmain;
	int crewcount,dockcount;
	double sunangle;
};

class ORION : public API {
public:
	ORION (OBJHANDLE hObj, int fmodel);
	void SlamCycle(double da);
	void VectorThrust();
	void PlaceComponents();
	void DestroyNeighbors(bool nukestep);
	void SetMainStage();
	void SetUpOrion();
	void InitialiseGuidance();
	void SetAttControlsOrion();
	void SetOrionStage();
	void clbkPreStep(double simt, double simdt, double mjd);
	void clbkPostStep(double simt, double simdt, double mjd);
	void clbkSetClassCaps(  FILEHANDLE cfg );
	void clbkLoadStateEx( FILEHANDLE scn, void *vs );
	void clbkSaveState(  FILEHANDLE scn );
	int clbkConsumeBufferedKey(DWORD key, bool down, char *kstate);
	int clbkConsumeDirectKey (char *kstate);
	void clbkVisualCreated( VESSEL *vessel, VISHANDLE vis, int refcount );
	//void clbkDrawHUD(int mode, const HUDPAINTSPEC *hps, HDC hDC);
	bool clbkDrawHUD(int mode, const HUDPAINTSPEC *hps, oapi::Sketchpad *skp);
	void clbkFocusChanged(bool getfocus, OBJHANDLE hNewVessel, OBJHANDLE hOldVessel);
	void UpdateHUDdata(int mode);
///
	UMMUCREWMANAGMENT Crew;
	int SelectedUmmuMember;				// for the SDK demo, select the member to eva
	int SelectedUmmuDock;				// Crew.SetActiveDockForTransfer(0);
	int iActionAreaDemoStep;			// this is just to show one feature of action area.
	void clbkSetClassCaps_UMMu(void);	// our special SetClassCap function just added for more readability

	void getsuperstructuremass(VESSEL * ship);

	// The HUD display method variable, see PDF doc
	char cUmmuHudDisplay[255];			// UMmu hud char variable
	double dHudMessageDelay;			// UMmu hud display delay
	char *SendHudMessage(void);			// UMmu hud display function
	LightEmitter *evalight;
	LightEmitter *boom;

	// THIS IS FOR ADDING CREW SEE PDF doc "Allow user to add crew to your ship 
	// without scenery editor"
	char cAddUMmuToVessel[255];
	void AddUMmuToVessel(BOOL bStartAdding=FALSE);
	void ummu_clbkPostStep(double simt, double simdt, double mjd);
	int ummu_selectdock(int i);
	int ummu_selectmember(int idx);
	int armnuke(int onoff);
	void chyield(int updown);
	void docklight();
///
	void hudprint(oapi::Sketchpad *skp, int x, int y, char buf[1024]);

	void drawbox(oapi::Sketchpad *skp, int x, int y, int height, int width, double ratio);

	VECTOR3 getrcsshift(VECTOR3 ofs);
	void chhud(int num);
	void chcam(int camnum);
	void chcamapt(int inout);
	void chcamdir(int xyz,int leftright,double ang=0.0);
	void rcs_linshift(int onoff);
	void rcs_linshift_group(THGROUP_TYPE g, double xratio, double yratio, double fzratio, double bzratio);
	void EulerToQuaternion(double yaw, double pitch, double roll);

	double dirrot2angle(VECTOR3 v,VECTOR3 h);

	VECTOR3 ORION::rotatex(VECTOR3 dir,double x);
	VECTOR3 ORION::rotatey(VECTOR3 dir,double y);
	VECTOR3 ORION::rotatez(VECTOR3 dir,double z);
	VECTOR3 ORION::yawpitch2cart(double yaw, double pitch);
	void ummuret(int Returned);
	void RefurbishOrion();	
	OBJHANDLE hV;
	int i, j;
	VECTOR3 EVAPOS;
	double cam1apt;
	enum RCS_SHIFT_MODES {
		RCS_NEUTRAL, RCS_SHIFTING, RCS_SHIFTED
	};
	ORIONCFG * cfg;
 	ORIONHUDDATA * hdata;
oapi::Sketchpad *vskp;
protected:
	int vhudCreated;
	SURFHANDLE vhud;
	oapi::Sketchpad * vhudskp;
    oapi::Font *hudfont;
	PROPELLANT_HANDLE ph_main, ph_RCS, ph_GYRO;
	THRUSTER_HANDLE th_main[1];
	THRUSTER_HANDLE th_orion[1];

	THGROUP_HANDLE thg_main;
	THGROUP_HANDLE thg_orion;
	MESHHANDLE  hOrionP, hOrionM, hOrionH,hOrionSc;
	SURFHANDLE  tex;
	DOCKHANDLE dock0, dock1, dock2, dock3, dock4, dock5, dock6, dock7, dock8;
	ATTACHMENTHANDLE CAMforward,CAMuprear,CAMdownrear;

	VECTOR3 AngularVel;
	char payloadmesh[256];
	char destructname[256];
	UINT anim_slam;
	UINT anim_sc;
	UINT testanim_camx,testanim_camy;
	UINT nuke;
	bool havesound;
	bool MoveNegative, firstnukestep;
	bool gpds_gui_active;
	bool UnDockArm;
	char hudlastmsg[256];
	char hudtitle[256];
	char dstr[1024];
	double distance;
	double slam_proc, sc_proc;
	//double testcamx_proc;
//	double jiggle_proc;
	int numevas;
//	int bombcounter;
	double tempP, tempY;
	double da,rcstimer,boomtimer;
	int MyID;
	int shifttest;
	//int hudmode;
	int boomcount,lcount;
	int rot_comp_mode;
	double rot_comp_level;
//	DWORD hudfontcolor,hudshadowcolor,hudselcolor,hudmesgcolor;
	VECTOR3 gorion, gpos, lpos, olpos;
	PSTREAM_HANDLE cloud;
	VECTOR3 rcs_shift_vec,shipcg;
	int rcs_shift_mode;
	int lin_shift_mode;
	int SSCOUNT;
	int syslogp;
	double ssmass;
	enum {HUD_OFF,HUD_MAIN,HUD_RCS,HUD_EVA,HUD_CAMERA};
	
	typedef struct sSUPERSTRUCTURE {
		OBJHANDLE ref;
	};
	#define MAXSUPERSTRUCTUREDEPTH 32
    sSUPERSTRUCTURE superstructure[MAXSUPERSTRUCTUREDEPTH];

	typedef struct sCAMERAS {
		VECTOR3 pos;
		VECTOR3 dir;
		double apt;
		//char * name;
		char name[32];
		UINT anim_yaw,anim_pitch;
		double yaw_proc,pitch_proc,lastyaw,lastpitch;
		//MGROUP_ROTATE * RotX;
		
	} *Cameras;
	#define NUMCAMS 4
	sCAMERAS cameras[NUMCAMS];
	sCAMERAS defcams[NUMCAMS];

	typedef struct sDOCKS {
		VECTOR3 pos,dir,rot;
		DOCKHANDLE handle;
		OBJHANDLE docked;
		VESSEL * dockedv;
		bool selected;
		double air;
		char dockedname[64];
	};
	#define NUMDOCKS 9
	sDOCKS docks[NUMDOCKS];

	/*cameras[] = {
		{_V(0,0,38.0),_V(0,0,1),60.0,0.0,0.0},
		{_V(0,7.655,17),_V(0,0,1),60.0,0.0,0.0},
		{_V(0,3,38),_V(0,0,1),60.0,0.0,0.0}
	};
*/

	#define SYSLOGSIZE 15
	typedef struct SHIPSYSLOG {
		char message[1024];
	};
	SHIPSYSLOG shiplog[SYSLOGSIZE];
};


#endif
